<!--
 * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
 * No deletion without permission, or be held responsible to law.
 * @author ThinkGem
-->
<template>
  <div :class="`jeesite-bpm-btns ${props.size}`">
    <div>
      <a-button type="default" @click="close" :size="props.size">
        <Icon icon="i-ant-design:close-outlined" />{{ t('common.cancelText') }}
      </a-button>
    </div>
    <div v-if="traceText != '' && !isEmpty(taskRef?.procIns?.id)">
      <a-button type="primary" @click="trace" :size="props.size">
        {{ t(traceText) }}
      </a-button>
    </div>
    <div
      v-if="
        getAuth &&
        needClaim &&
        backText != '' &&
        taskRef.procIns?.procDef?.form?.optionMap?.allowBackTask != '0'
      "
    >
      <a-button color="error" @click="back" :size="props.size">
        {{ t(backText) }}
      </a-button>
    </div>
    <div
      v-if="
        getAuth &&
        needClaim &&
        turnText != '' &&
        taskRef.procIns?.procDef?.form?.optionMap?.allowTurnTask != '0'
      "
    >
      <a-button color="warning" @click="turn(false)" :size="props.size">
        {{ t(turnText) }}
      </a-button>
    </div>
    <div
      v-if="
        getAuth &&
        needClaim &&
        delegateText != '' &&
        taskRef.procIns?.procDef?.form?.optionMap?.allowDelegateTask != '0'
      "
    >
      <a-button color="success" @click="turn(true)" :size="props.size">
        {{ t(delegateText) }}
      </a-button>
    </div>
    <div
      v-if="
        getAuth &&
        needClaim &&
        taskRef.hasMultiInstance &&
        taskRef.procIns?.procDef?.form?.optionMap?.allowModifySignTask != '0'
      "
    >
      <a-button class="purple" @click="modifySign()" :size="props.size">
        {{ t(modifySignText) }}
      </a-button>
    </div>
    <div
      v-if="
        getAuth &&
        needClaim &&
        stopText != '' &&
        (taskRef.procIns?.startUserId == userInfo.userCode || userInfo.userCode == 'system') &&
        taskRef.procIns?.procDef?.form?.optionMap?.allowStop != '0'
      "
    >
      <a-button color="error" @click="stop" :size="props.size">
        {{ t(stopText) }}
      </a-button>
    </div>
    <div
      v-if="
        getAuth &&
        needClaim &&
        moveText != '' &&
        (userInfo.userCode == 'system' ||
          taskRef.procIns?.procDef?.form?.optionMap?.allowMoveTask == '1')
      "
    >
      <a-button color="warning" @click="move" :size="props.size">
        {{ t(moveText) }}
      </a-button>
    </div>
    <div
      v-if="
        getAuth &&
        rollbackText != '' &&
        taskRef.procIns?.procDef?.form?.optionMap?.allowRollbackTask != '0' &&
        !isEmpty(taskRef.procIns?.id) &&
        (taskRef.procIns?.endTime == null || taskRef.procIns?.endTime == '') &&
        !isEmpty(taskRef.id) &&
        !(taskRef.endTime == null || taskRef.endTime == '') &&
        taskRef.assignee == userInfo.userCode
      "
    >
      <a-button color="error" @click="rollback" :size="props.size">
        {{ t(rollbackText) }}
      </a-button>
    </div>
    <div v-if="getAuth && isInit && isEmpty(taskRef.procIns?.id) && draft">
      <a-button color="success" @click="completeDraft" :loading="loading" :size="props.size">
        <Icon icon="i-ant-design:save-outlined" /> {{ t(draftText) }}
      </a-button>
    </div>
    <div v-if="getAuth && isInit && isEmpty(taskRef.procIns?.id)">
      <a-button type="primary" @click="complete" :loading="loading" :size="props.size">
        <Icon icon="i-ant-design:check-outlined" /> {{ t(completeText) }}
      </a-button>
    </div>
    <div
      v-if="
        getAuth &&
        taskClaim &&
        (taskRef.assignee == null || taskRef.assignee == '') &&
        taskRef.assignee != userInfo.userCode
      "
    >
      <a-button color="success" @click="claim" :loading="loading" :size="props.size">
        <Icon icon="i-ant-design:check-outlined" /> {{ t(claimText) }}
      </a-button>
    </div>
    <div v-if="getAuth && needClaim">
      <a-button type="primary" @click="complete" :loading="loading" :size="props.size">
        <Icon icon="i-ant-design:check-outlined" /> {{ t(completeText) }}
      </a-button>
    </div>
    <BpmUserSelect @register="registerUserSelectModal" @select="userSelectOk" />
    <BpmTaskComplete @register="registerCompleteModal" @success="completeOk" />
    <BpmTaskBack @register="registerBackModal" @success="success" />
    <BpmTaskTurn @register="registerTurnModal" @success="success" />
    <BpmTaskModifySign @register="registerModifySignModal" />
    <BpmRuntimeStop @register="registerStopModal" @success="success" />
    <BpmRuntimeTrace @register="registerTraceModal" />
  </div>
</template>
<script lang="ts" setup name="JeeSiteBpmButton">
  import { computed, watch, ref } from 'vue';
  import Icon from '/@/components/Icon/src/Icon.vue';
  import { propTypes } from '/@/utils/propTypes';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { usePermission } from '/@/hooks/web/usePermission';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { useUserStore } from '/@/store/modules/user';
  import { useModal } from '/@/components/Modal';
  import { isEmpty } from '/@/utils/is';
  import { BpmTask, bpmGetTask, bpmClaim, bpmRollback /*, bpmGetNextUser*/ } from '/@/api/bpm';
  import BpmUserSelect from './BpmUserSelect.vue';
  import BpmTaskComplete from './BpmTaskComplete.vue';
  import BpmTaskBack from './BpmTaskBack.vue';
  import BpmTaskTurn from './BpmTaskTurn.vue';
  import BpmTaskModifySign from './BpmTaskModifySign.vue';
  import BpmRuntimeStop from './BpmRuntimeStop.vue';
  import BpmRuntimeTrace from './BpmRuntimeTrace.vue';

  const emit = defineEmits([
    // 'update:bpmEntity',
    'initialize',
    'userSelect',
    'validate',
    'complete',
    'claim',
    'back',
    'turn',
    'delegate',
    'modifySign',
    'stop',
    'move',
    'trace',
    'rollback',
    'success',
    'close',
  ]);

  const { t } = useI18n('bpm.button');
  const { hasPermission } = usePermission();
  const { createConfirm, showMessageModal, showMessage } = useMessage();
  const userStore = useUserStore();
  const userInfo = userStore.getUserInfo;

  const props = defineProps({
    // 业务实体对象
    bpmEntity: {
      type: Object as PropType<Recordable>,
      default: () => {},
    },
    // 关联表单Key
    formKey: propTypes.string.def(''),

    // 是否启用草稿（草稿状态9，提交审核状态4）
    draft: propTypes.bool.def(true),
    claimText: propTypes.string.def('签收'),
    draftText: propTypes.string.def('草稿'),
    completeText: propTypes.string.def('提交'),
    completeModal: propTypes.bool.def(false),

    // 退回到之前办理过的任务环节
    backText: propTypes.string.def('退回'),

    // 将任务转交他人办理，办理完成后继续流转
    turnText: propTypes.string.def('转办'),

    // 任务交由被委托人办理，办理完成后返回委托人
    delegateText: propTypes.string.def('委托'),

    // 任务加签或减签操作
    modifySignText: propTypes.string.def('加减签'),

    // 单据作废，结束流程实例
    stopText: propTypes.string.def('终止'),

    // 特事特办，自由流，自由跳转
    moveText: propTypes.string.def(''),

    // 流程状态，流程图，流程记录
    traceText: propTypes.string.def('流程图'),

    // 下一环节未审批的可撤回重做
    rollbackText: propTypes.string.def('撤回任务'),

    // 按钮加载状态
    loading: propTypes.bool.def(false),

    // 按钮权限字符串
    auth: propTypes.string.def(''),

    // 按钮大小
    size: propTypes.string.def('middle'),

    // 异步事件是组件的事件行为是异步执行的
    asyncEmits: {
      type: Array as PropType<string[]>,
      default: () => ['userSelect', 'validate'],
    },
  });

  const getAuth = computed(() => {
    return hasPermission(props.auth);
  });

  const bizKeyRef = ref<String>('');
  const bpmEntityRef = ref<Recordable>({});
  const formDataRef = ref<Recordable>({});
  const taskRef = ref<BpmTask>({});

  const isInit = ref(false);
  const taskClaim = ref(false);
  const needClaim = ref(false);

  const [registerUserSelectModal /*, { openModal: openUserSelectModal }*/] = useModal();
  const [registerCompleteModal, { openModal: completeModel }] = useModal();
  const [registerBackModal, { openModal: backModel }] = useModal();
  const [registerTurnModal, { openModal: turnModel }] = useModal();
  const [registerModifySignModal, { openModal: modifySignModel }] = useModal();
  const [registerStopModal, { openModal: stopModel }] = useModal();
  const [registerTraceModal, { openModal: traceModel }] = useModal();

  watch(
    () => props.bpmEntity,
    () => {
      isInit.value = false;
      taskClaim.value = false;
      needClaim.value = false;
      const newId = props.bpmEntity['id'];
      const currId = props.bpmEntity['id'];
      const newBpm = props.bpmEntity['bpm'] || {};
      const currBpm = bpmEntityRef.value['bpm'] || {};
      if (!currId || newId != currId || !currBpm.taskId || newBpm.taskId != currBpm.taskId) {
        // console.log('id', newId, currId);
        // console.log('bpm', newBpm, currBpm);
        bizKeyRef.value = newId;
        bpmEntityRef.value = props.bpmEntity;
        loadData();
      }
    },
    { immediate: true },
  );

  async function loadData() {
    const currBpm = bpmEntityRef.value['bpm'] || {};
    const taskId = currBpm.taskId || '';
    // const procInsId = currBpm.procInsId || '';
    const formKey = props.formKey || '';
    const bizKey = bizKeyRef.value || '';
    if (taskId != '' || (formKey != '' && bizKey != '')) {
      const res = await bpmGetTask({
        id: taskId,
        'procIns.formKey': formKey,
        'procIns.bizKey': bizKey,
      });
      initialize(res);
    } else {
      initialize();
    }
    isInit.value = true;
  }

  function initialize(task: Recordable = {}) {
    const currBpm = bpmEntityRef.value['bpm'] || {};
    if (!task.id || task.id == '') {
      task.id = currBpm.taskId || '';
    }
    if (!task.procIns) {
      task.procIns = {};
    }
    if (!task.procIns.id || task.procIns.id == '') {
      task.procIns.id = currBpm.procInsId || '';
    }
    if (task.procIns.id == '') {
      taskClaim.value = false;
      needClaim.value = false;
    } else if (task.id != '' && (task.endTime == null || task.endTime == '')) {
      if (task.assignee == null || task.assignee == '') {
        taskClaim.value = true;
        needClaim.value = false;
      } else {
        taskClaim.value = false;
        needClaim.value = true;
      }
    }
    taskRef.value = task;
    // console.log('task', task);
    currBpm.taskId = task.id || '';
    currBpm.procInsId = task.procIns?.id || '';
    currBpm.activityId = task.activityId || '';
    currBpm.status = task.status;
    bpmEntityRef.value['bpm'] = currBpm;
    // console.log('bpm', bpmEntityRef.value);
    // emit('update:bpmEntity', bpmEntityRef.value);
    emit('initialize', task, currBpm);
  }

  // 提交按钮
  function complete() {
    // // 提交之前弹窗选择下一步处理人（根据业务需要启用）
    // emitPlus('userSelect', async (params) => {
    //   const res = await bpmGetNextUser(params);
    //   const { nextUsers, office } = res;
    //   const roleCodes: string[] = [];
    //   if (nextUsers) {
    //     nextUsers.forEach((e: Recordable) => {
    //       if (e.roleCodes) {
    //         roleCodes.push(e.roleCodes.join(','));
    //       }
    //     });
    //   }
    //   if (roleCodes.length > 0) {
    //     openUserSelectModal(true, {
    //       checkbox: false,
    //       roleCode: roleCodes.join(','),
    //       office,
    //     });
    //   } else {
    //     userSelectOk();
    //   }
    // });
    // if (props.completeModal) {
    //   emitPlus('validate', async (formData: any) => {
    //     formDataRef.value = formData || {};
    //     completeModel(true, { task: taskRef.value });
    //   });
    // } else {
    //   userSelectOk();
    // }
    userSelectOk();
  }

  // 提交对话框的提交
  function completeOk(bpm: Recordable) {
    Object.assign(bpmEntityRef.value.bpm, bpm);
    // console.log(bpmEntityRef.value);
    userSelectOk();
  }

  // 用户选择后的提交
  function userSelectOk(data?: Recordable) {
    if (data) {
      const userCodes: string[] = [];
      data.forEach((e) => {
        userCodes.push(e.userCode);
      });
      bpmEntityRef.value.bpm.nextUserCodes = userCodes.join(',');
    }
    bpmEntityRef.value.status = 4; // 状态：4:审核；9:草稿
    // emit('update:bpmEntity', bpmEntityRef.value);
    // formDataRef.value.bpm = Object.assign(formDataRef.value.bpm || {}, bpmEntityRef.value.bpm); // 流程信息
    // formDataRef.value.status = bpmEntityRef.value.bpm.status; // 提交状态
    emitPlus('complete', (_res: any) => {
      // 有业务功能实现
    });
  }

  // 草稿按钮
  function completeDraft() {
    const draftFn = () => {
      bpmEntityRef.value.status = 9; // 状态：4:审核；9:草稿
      // emit('update:bpmEntity', bpmEntityRef.value);
      emitPlus('complete', (_res: any) => {
        // 有业务功能实现
      });
    };
    if (props.completeModal) {
      emitPlus('validate', async (formData: any) => {
        formDataRef.value = formData || {};
        draftFn();
      });
    } else {
      draftFn();
    }
  }

  // 签收按钮
  function claim() {
    emitPlus('claim', async (_res: any) => {
      const res = await bpmClaim({ id: taskRef.value.id });
      showMessage(res.message);
      loadData();
    });
  }

  // 退回按钮
  function back() {
    emitPlus('back', async (_res: any) => {
      backModel(true, { task: taskRef.value });
    });
  }

  // 转发或委托按钮
  function turn(turnDelegate: boolean) {
    emitPlus(turnDelegate ? 'delegate' : 'turn', (_res: any) => {
      turnModel(true, { task: taskRef.value, turnDelegate });
    });
  }

  // 加减签按钮
  function modifySign() {
    emitPlus('modifySign', async (_res: any) => {
      modifySignModel(true, { task: taskRef.value });
    });
  }

  // 终止流程按钮
  function stop() {
    emitPlus('stop', (_res: any) => {
      stopModel(true, { procIns: taskRef.value.procIns });
    });
  }

  // 特事特办按钮
  function move() {
    emitPlus('move', (_res: any) => {});
  }

  // 流程图按钮
  function trace() {
    emitPlus('trace', (_res: any) => {
      traceModel(true, taskRef.value.procIns);
    });
  }

  // 撤销按钮
  function rollback() {
    emitPlus('rollback', (_res: any) => {
      createConfirm({
        title: t('提示'),
        content: t(
          '如果该任务的下一环节未被处理，则可以尝试撤回该任务的办理。您确认要尝试撤回吗？',
        ),
        iconType: 'warning',
        onOk: async (_res) => {
          try {
            const res = await bpmRollback({ id: taskRef.value.id });
            showMessageModal({ content: res.message });
            success();
          } catch (error: any) {
            console.log('error', error);
          }
          return Promise.resolve();
        },
      });
    });
  }

  // 事件调用增强扩展，如果父组件没有实现该事件，则调用默认事件默认事件
  // 如果实现该事件，则第一行代码就调用 callback(false)，则终止默认事件
  // 举例，父组件实现事件 @complete="handleComplete" 该方法实现如下：
  // /**
  //  * 举例实现完成事件
  //  * @param data 调用 emitPlus 事件，第二个参数传递的数据
  //  * @param callback 调用 (defaultEvenCall, newData) 方法的函数
  //  * @author ThinkGem
  //  */
  // function handleComplete(data, callback) {
  //    const defaultEventCall = false; // 终止默认事件
  //    const defaultEventCall = true; // 继续执行默认事件
  //    const newData = {}; // 给默认事件传递的参数数据
  //    callback(defaultEventCall, newData);
  // }
  async function emitPlus(name: any, defaultEvent: any) {
    //console.log(name, taskRef.value)
    let res = true;
    let data = {};
    emit(
      name,
      {
        task: taskRef.value,
        formData: props.completeModal ? formDataRef.value : undefined,
      },
      (defaultEventCall: any, newData: any) => {
        if (defaultEventCall != undefined) {
          res = defaultEventCall;
        }
        if (newData != undefined) {
          data = newData;
        }
        if (res && props.asyncEmits.includes(name)) {
          defaultEvent(data);
        }
      },
    );
    if (res && !props.asyncEmits.includes(name)) {
      defaultEvent(data);
    }
  }

  function success() {
    emit('success');
    emit('close');
  }

  function close() {
    emit('close');
  }
</script>
<style lang="less">
  .jeesite-bpm-btns {
    display: inline-block;
    overflow: auto hidden;
    white-space: nowrap;
    padding-right: 8px;
    width: 100%;

    > div {
      display: inline-block;
      padding-left: 8px;
    }

    &.small {
      overflow: visible;

      > div {
        padding-left: 0;
      }
    }
  }

  u-popup {
    display: none;
  }

  .form-title {
    font-size: 34rpx;
    padding: 28rpx 30rpx 10rpx;
  }

  .form-footer {
    margin: 0;
    padding: 0 10rpx;
    padding-bottom: 20rpx;
  }
</style>
